package com.fz.security.filter;

import com.fz.dto.client.login.WxAuthDto;
import com.fz.security.tokens.MobileCodeAuthenticationToken;
import com.fz.security.tokens.MobilePwdAuthenticationToken;
import com.fz.security.tokens.WeChatAuthenticationToken;
import com.fz.utils.JacksonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * @author yh
 * @date 2020/5/18 15:58
 * @desc
 */
public class BhAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    // ~ Static fields/initializers
    // =====================================================================================

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
    public static final String SPRING_SECURITY_FORM_AUTYPE_KEY = "autype";

    private String username = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String password = SPRING_SECURITY_FORM_PASSWORD_KEY;
    private String autype = SPRING_SECURITY_FORM_AUTYPE_KEY;

    protected final Logger logger = LoggerFactory.getLogger(BhAuthenticationFilter.class.getSimpleName());

    // ~ Constructors
    // ===================================================================================================

    public BhAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String username = obtainUsername(request);
        String password = obtainPassword(request);
        String autype = obtainAutype(request);
        System.out.println(this.getClass().getName() + "----autype:" + autype);

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        if (autype == null) {
            autype = "";
        }

        username = username.trim();

        AbstractAuthenticationToken authRequest = null;
        switch(autype) {
            case "mobileCode":
                authRequest = new MobileCodeAuthenticationToken(username, password);
                break;
            default:
                authRequest = new UsernamePasswordAuthenticationToken(username, password);
                break;
        }

        /*UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                username, password);*/

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }



    /**
     * @方法描述: 手机号验证码登录与注册
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public Authentication attemptAuthenticationByMc(
            String mobilePhone,String code,
            HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException{
        AbstractAuthenticationToken authRequest = null;
        authRequest = new MobileCodeAuthenticationToken(mobilePhone, code);
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * @方法描述: 手机号密码登录
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public Authentication attemptAuthenticationByMp(
            String mobilePhone,String password,
            HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
        AbstractAuthenticationToken authRequest = null;
        authRequest = new MobilePwdAuthenticationToken(mobilePhone, password);
        setDetails(request, authRequest);
         return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * @方法描述: 微信授权登录
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public Authentication attemptAuthenticationByWechat(
            WxAuthDto wxAuthDto,
            HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
        AbstractAuthenticationToken authRequest = null;
        //将传输过来的dto对象转为json字符串
        String jsonStr = JacksonUtils.obj2String(wxAuthDto);
        authRequest = new WeChatAuthenticationToken(jsonStr,wxAuthDto.getUnionId());
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }




    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(password);
    }

    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(username);
    }

    protected String obtainAutype(HttpServletRequest request) {
        return request.getParameter(autype);
    }

    protected void setDetails(HttpServletRequest request,
                              AbstractAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public void setAutypeParameter(String autype) {
        Assert.hasText(autype, "Autype parameter must not be empty or null");
        this.autype = autype;
    }

    public void setUsernameParameter(String username) {
        Assert.hasText(username, "Username parameter must not be empty or null");
        this.username = username;
    }

    public void setPasswordParameter(String password) {
        Assert.hasText(password, "Password parameter must not be empty or null");
        this.password = password;
    }

    public final String getUsernameParameter() {
        return username;
    }

    public final String getPasswordParameter() {
        return password;
    }
}
